//
//  HybridWebView.swift
//  MeenoHybrid
//
//  Created by alyadan on 2016/10/22.
//  Copyright © 2016年 alyadan. All rights reserved.
//

import Foundation
import RxSwift
import JavaScriptCore

class HybridWebView: UIWebView, UIWebViewDelegate {
    
    public override var currentModel: HybridWebViewModel? {
        
        return viewModel.value as? HybridWebViewModel
        
    }
    
    public var mainHandler :MNWebViewMainHandler! {
        return currentModel!.mainHandler
    }
    
    public init(hybrdViewModel: HybridWebViewModel){
        
        super.init(frame: CGRect.zero)
        self.viewModel.value = hybrdViewModel
        initView()
    }
    
    
    public required init?(coder: NSCoder) {
        
        super.init(coder: coder)
        
    }
    
    
    @objc public override func setupUI() {
        
        self.dataDetectorTypes = UIDataDetectorTypes(rawValue: 0)
        self.backgroundColor = UIColor.clear
        self.isOpaque = false
        
        // create bridge
        let mainBundle = Bundle.main.url(forResource: "WebViewJavascriptBridge", withExtension: "bundle")
        
        
        currentModel?.bridge = WebViewJavascriptBridge(for: self, webViewDelegate: self, handler:
            {[unowned self] (data, callback) in
                
                do{
                    
                    try self.mainHandler.deal(data: data, responseCallback: callback!)
                    
                }catch HybridBaseHandler.HybridError.dataParamError{
                    
                    
                    self.mainHandler.callbackParamError(callback: callback)
                    
                }catch HybridBaseHandler.HybridError.methodError{
                    
                    self.mainHandler.callbackMethodError(callback: callback)
                    
                }catch HybridBaseHandler.HybridError.pluginError{
                    
                    self.mainHandler.callbackFail(callback: callback, error: 10, subError: 0, errMsg: "plugin error")
                    
                }catch{
                    
                    print(error)
                }
                
            }, resourceBundle: Bundle.init(url: mainBundle!))
        
        if let x = currentModel?.bridge{
            
            //特殊处理
            mainHandler.register(bridge: x, webViewModel: currentModel!)
            //
            
            HybridHandlerCenter.share.register(bridge: x, webViewModel: currentModel!)
            
        }else{
            
            print("error: webBridge create failed!")
            
        }
        
        
        
        // export method to js
        if let context = self.value(forKeyPath: "documentView.webView.mainFrame.javaScriptContext" ) as? JSContext {
            
            context.setObject(aSyncManager(), forKeyedSubscript: NSString.init(string: "SyncManager"))
        }
        
        
        //load url
        if let url = currentModel?.completeUrl{
            
            print(url.absoluteString)
            
            if MeenoHybrid.use_local_html {
                
                self.loadRequest(URLRequest.init(url: url))
                
            }else {
                
                let req = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 30)
                self.loadRequest(req)
            }
        }
        
        
        
    }
    
    
    public override func bindModelData() {
        
        let enterForeground = ["method":"appWillEnterForground", "data":[String:Any]()] as [String : Any]
        let enterBackground = ["method":"appDidEnterBackground", "data":[String:Any]()] as [String : Any]
        let sub1 = NotificationCenter.default.rx.notification(Notification.Name.UIApplicationWillEnterForeground).shareReplay(1)
        let sub2 = NotificationCenter.default.rx.notification(Notification.Name.UIApplicationDidEnterBackground).shareReplay(1)
        Observable.of(sub1, sub2).merge().bindNext {[unowned self] (x:Notification) in
            switch x.name {
            case Notification.Name.UIApplicationDidEnterBackground:
                
                self.currentModel?.bridge?.send(enterBackground)
                //                self.currentModel?.bridge?.callHandler(data: enterBackground)
                
            case Notification.Name.UIApplicationWillEnterForeground:
                self.currentModel?.bridge?.send(enterForeground)
            //                self.currentModel?.bridge?.callHandler(data: enterForeground)
            default:
                break
            }
            }.addDisposableTo(disposeBag)
        
        
        //Refresh 
        currentModel?.isReloding.asObservable()
            .bindNext(
                {[unowned self] b in
                    self.reload()
                }).addDisposableTo(disposeBag)
        
        currentModel?.isDownRefresh.asObservable()
            .bindNext(
                {[unowned self] b in
                    if b {
                        self.scrollView.mj_header?.beginRefreshing()
                    }else {
                        self.scrollView.mj_header?.endRefreshing()
                    }
                }).addDisposableTo(disposeBag)
        
        currentModel?.isUPRefresh.asObservable()
            .bindNext(
                {[unowned self] b in
                    if b {
                        self.scrollView.mj_footer?.beginRefreshing()
                    }else {
                        self.scrollView.mj_footer?.endRefreshing()
                    }
                }).addDisposableTo(disposeBag)
        
        currentModel?.refreshType.asObservable()
            .bindNext(
                { [unowned self] type in
                    switch type {
                    case 0:
                        self.addDownRefresh()
                    case 1:
                        self.addUpRefresh()
                    case 2:
                        self.addUpRefresh()
                        self.addDownRefresh()
                    default:
                        break;
                    }
                }).addDisposableTo(disposeBag)
        
        currentModel?.dragable.asObservable()
            .bindNext({ [unowned self] (dragable: Bool) in
                
                self.scrollView.bounces = dragable
                
        }).addDisposableTo(disposeBag)
        
    }
    
    func addUpRefresh() {
        self.scrollView.mj_header = MJRefreshNormalHeader(refreshingBlock:
            { [unowned self] in
                self.currentModel?.bridge?.send(HybridBaseHandler.createSendData(method: "cbDownRefreshData"))
                
            })
    }
    
    func addDownRefresh() {
        self.scrollView.mj_footer = MJRefreshBackNormalFooter(refreshingBlock:
            {
                [unowned self] in
                self.currentModel?.bridge?.send(HybridBaseHandler.createSendData(method: "cbUpLoadData"))
            })
        
    }
    
    //MARK:WKNavigationDelegate
    public func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        
        print("start webview")
        
    }
    
    public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        
        
        print("finish webview")
        
        
    }
    
    func webViewDidFinishLoad(_ webView: UIWebView) {
        
        self.stringByEvaluatingJavaScript(from: "document.documentElement.style.webkitUserSelect='none';")
        self.stringByEvaluatingJavaScript(from: "document.documentElement.style.webkitTouchCallout='none';")
        
    }
    
    deinit {
        print("\(self) deinit")
    }
    
}

public class HybridWebViewModel: HybridBaseWebViewModel {
    
    public var bridge:WebViewJavascriptBridge?
    
    
    
}
